package com.xf.poc.fixtool.test;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.font.TextAttribute;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;

public class GuitarFretboardTrainer extends JFrame {
    private static final long serialVersionUID = 1L;
    private JLabel questionLabel, resultLabel, timerLabel, selectedNoteLabel, questionNumberLabel;
    private JButton startButton, stopButton, nextButton;
    private Timer questionTimer;
    private int currentString, currentFret;
    private Map<Integer, String> notesMap;
    private int questionTime = 5; // 默认问题显示时间为5秒
    private boolean questionActive = false;
    private boolean timeExpired = false;
    private JComboBox<String> noteTypeComboBox;
    private String selectedNote = "";
    private List<JButton> noteButtons;
    private String correctAnswer = "";
    private static final Color PRIMARY_COLOR = new Color(65, 105, 225); // 皇家蓝
    private static final Color SUCCESS_COLOR = new Color(60, 179, 113); // 中绿色
    private static final Color ERROR_COLOR = new Color(220, 53, 69);   // 番茄红
    private static final Color WARNING_COLOR = new Color(255, 165, 0); // 橙色
    private static final Color BACKGROUND_COLOR = new Color(248, 249, 250); // 浅灰背景
    private static final Color BUTTON_COLOR = new Color(65, 105, 225); // 按钮颜色
    private static final Color BUTTON_HOVER_COLOR = new Color(52, 91, 204); // 按钮悬停颜色
    private static final int MIN_WIDTH = 320; // 最小宽度
    private static final int MIN_HEIGHT = 480; // 最小高度
    private JCheckBox timerCheckBox; // 计时复选框
    private boolean useTimer = false; // 默认使用计时器
    private int questionCount = 0; // 问题计数
    private int correctCount = 0; // 正确题数
    private int wrongCount = 0; // 错误题数
    private long startTime; // 开始时间
    private JLabel statsLabel; // 统计信息标签

    public GuitarFretboardTrainer() {
        // 设置全局字体
        initGlobalFont();

        // 初始化音符映射
        initNotesMap();

        // 设置窗口
        setTitle("");
        setSize(800, 600);
        setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setLayout(new BorderLayout());
        getContentPane().setBackground(BACKGROUND_COLOR);

        // 添加窗口大小变化监听器
        addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                adjustComponentsForSize();
            }
        });

        // 创建主面板 - 使用自适应的GridBagLayout
        JPanel mainPanel = new JPanel(new GridBagLayout());
        mainPanel.setBackground(BACKGROUND_COLOR);
        mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.insets = new Insets(10, 10, 10, 10);
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.anchor = GridBagConstraints.CENTER;
        gbc.weightx = 1.0;

        // 问题编号标签
        questionNumberLabel = new JLabel("第 0 题");
        questionNumberLabel.setFont(new Font("微软雅黑", Font.BOLD, 20));
        questionNumberLabel.setForeground(PRIMARY_COLOR);
        questionNumberLabel.setHorizontalAlignment(JLabel.CENTER);
        mainPanel.add(questionNumberLabel, gbc);

        gbc.gridy++;
        // 问题标签
        questionLabel = new JLabel("");
        questionLabel.setFont(new Font("微软雅黑", Font.BOLD, 24));
        questionLabel.setForeground(PRIMARY_COLOR);
        questionLabel.setHorizontalAlignment(JLabel.CENTER);
        mainPanel.add(questionLabel, gbc);

        gbc.gridy++;
        // 结果标签
        resultLabel = new JLabel("");
        resultLabel.setFont(new Font("微软雅黑", Font.PLAIN, 20));
        resultLabel.setHorizontalAlignment(JLabel.CENTER);
        mainPanel.add(resultLabel, gbc);

        gbc.gridy++;
        // 计时器标签
        timerLabel = new JLabel("");
        timerLabel.setFont(new Font("微软雅黑", Font.PLAIN, 18));
        timerLabel.setForeground(PRIMARY_COLOR);
        timerLabel.setHorizontalAlignment(JLabel.CENTER);
        mainPanel.add(timerLabel, gbc);

        gbc.gridy++;
        // 已选音符标签
        selectedNoteLabel = new JLabel("你选择的: ");
        selectedNoteLabel.setFont(new Font("微软雅黑", Font.BOLD, 22));
        selectedNoteLabel.setForeground(PRIMARY_COLOR);
        selectedNoteLabel.setHorizontalAlignment(JLabel.CENTER);
        mainPanel.add(selectedNoteLabel, gbc);

        gbc.gridy++;
        // 音符选择按钮区域 - 使用自适应的FlowLayout
        JPanel noteButtonsPanel = new JPanel(new WrapLayout(FlowLayout.CENTER, 8, 8));
        noteButtonsPanel.setBackground(BACKGROUND_COLOR);
        noteButtons = new ArrayList<>();

        // 创建音符按钮
        String[] naturalNotes = {"C", "D", "E", "F", "G", "A", "B"};
        String[] sharpNotes = {"C#", "D#", "F#", "G#", "A#"};
        String[] flatNotes = {"Db", "Eb", "Gb", "Ab", "Bb"};

        // 自然音符按钮
        for (String note : naturalNotes) {
            JButton button = createStyledNoteButton(note);
            noteButtonsPanel.add(button);
            noteButtons.add(button);
        }

        // 升号音符按钮
        for (String note : sharpNotes) {
            JButton button = createStyledNoteButton(note);
            noteButtonsPanel.add(button);
            noteButtons.add(button);
        }

        // 降号音符按钮
        for (String note : flatNotes) {
            JButton button = createStyledNoteButton(note);
            noteButtonsPanel.add(button);
            noteButtons.add(button);
        }

        mainPanel.add(noteButtonsPanel, gbc);

        gbc.gridy++;
        // 开始/停止和下一题按钮
        JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 10));
        controlPanel.setBackground(BACKGROUND_COLOR);

        startButton = createStyledButton("开始");
        startButton.addActionListener(new StartButtonListener());
        controlPanel.add(startButton);

        stopButton = createStyledButton("停止");
        stopButton.addActionListener(new StopButtonListener());
        stopButton.setEnabled(false);
        controlPanel.add(stopButton);

        nextButton = createStyledButton("下一个");
        nextButton.addActionListener(new NextButtonListener());
        nextButton.setEnabled(false);
        controlPanel.add(nextButton);

        mainPanel.add(controlPanel, gbc);

        gbc.gridy++;
        // 音符类型选择
        JPanel noteTypePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 10));
        noteTypePanel.setBackground(BACKGROUND_COLOR);

        JLabel noteTypeLabel = new JLabel("练习类型: ");
        noteTypeLabel.setFont(new Font("微软雅黑", Font.PLAIN, 16));
        noteTypePanel.add(noteTypeLabel);

        String[] noteTypes = {"自然音", "升号音", "降号音"};
        noteTypeComboBox = new JComboBox<>(noteTypes);
        noteTypeComboBox.setFont(new Font("微软雅黑", Font.PLAIN, 16));
        noteTypeComboBox.setSelectedIndex(0); // 默认选择自然音
        noteTypeComboBox.addActionListener(e -> updateButtonVisibility());
        noteTypeComboBox.setPreferredSize(new Dimension(200, 30));
        noteTypePanel.add(noteTypeComboBox);

        mainPanel.add(noteTypePanel, gbc);

        gbc.gridy++;
        // 计时选项
        JPanel timerOptionPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 10));
        timerOptionPanel.setBackground(BACKGROUND_COLOR);

        timerCheckBox = new JCheckBox("启用计时", false);
        timerCheckBox.setFont(new Font("微软雅黑", Font.PLAIN, 16));
        timerCheckBox.setBackground(BACKGROUND_COLOR);
        timerCheckBox.addActionListener(e -> {
            useTimer = timerCheckBox.isSelected();
            if (useTimer) {
                if (questionActive) {
                    ((QuestionTimerListener) questionTimer.getActionListeners()[0]).secondsLeft = questionTime;
                    timerLabel.setText("剩余时间: " + questionTime + "秒");
                    questionTimer.restart();
                }
            } else {
                if (questionActive) {
                    questionTimer.stop();
                }
            }
        });
        timerOptionPanel.add(timerCheckBox);

        mainPanel.add(timerOptionPanel, gbc);

        gbc.gridy++;
        // 统计信息标签
        statsLabel = new JLabel("正确: 0 题, 错误: 0 题, 正确率: 0%, 用时: 0 秒");
        statsLabel.setFont(new Font("微软雅黑", Font.PLAIN, 16));
        statsLabel.setForeground(PRIMARY_COLOR);
        statsLabel.setHorizontalAlignment(JLabel.CENTER);
        mainPanel.add(statsLabel, gbc);

        // 添加主面板的滚动支持
        JScrollPane scrollPane = new JScrollPane(mainPanel);
        scrollPane.setBorder(null);
        scrollPane.getVerticalScrollBar().setUnitIncrement(16);
        add(scrollPane, BorderLayout.CENTER);

        // 添加键盘事件监听
        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                if (!questionActive) return;

                char keyChar = Character.toUpperCase(e.getKeyChar());

                // 处理自然音符
                if (keyChar >= 'A' && keyChar <= 'G') {
                    selectNote(String.valueOf(keyChar));
                }
                // 处理升号音符 (例如 S 对应 C#)
                else if (keyChar == 'S') {
                    selectNote("C#");
                } else if (keyChar == 'D') {
                    selectNote("D#");
                } else if (keyChar == 'G') {
                    selectNote("F#");
                } else if (keyChar == 'H') {
                    selectNote("G#");
                } else if (keyChar == 'J') {
                    selectNote("A#");
                }
                // 处理降号音符 (例如 X 对应 Db)
                else if (keyChar == 'X') {
                    selectNote("Db");
                } else if (keyChar == 'C') {
                    selectNote("Eb");
                } else if (keyChar == 'V') {
                    selectNote("Gb");
                } else if (keyChar == 'B') {
                    selectNote("Ab");
                } else if (keyChar == 'N') {
                    selectNote("Bb");
                }
                // 处理回车键提交
                else if (keyChar == KeyEvent.VK_ENTER && !selectedNote.isEmpty()) {
                    if (timeExpired) {
                        checkAnswerAfterTimeExpired();
                    } else {
                        checkAnswer();
                    }
                }
            }
        });

        // 设置窗体可聚焦以接收键盘事件
        setFocusable(true);
        requestFocus();

        // 初始化计时器
        questionTimer = new Timer(1000, new QuestionTimerListener());

        // 初始设置
        updateButtonVisibility();

        // 首次调整组件大小
        adjustComponentsForSize();

        setVisible(true);
    }

    // 初始化全局字体
    private void initGlobalFont() {
        Font defaultFont = new Font("微软雅黑", Font.PLAIN, 14);
        Map<TextAttribute, Object> attributes = new HashMap<>(defaultFont.getAttributes());
        attributes.put(TextAttribute.FAMILY, "微软雅黑");
        Font newFont = defaultFont.deriveFont(attributes);

        UIManager.put("Button.font", newFont);
        UIManager.put("Label.font", newFont);
        UIManager.put("ComboBox.font", newFont);
        UIManager.put("Slider.font", newFont);
        UIManager.put("TextField.font", newFont);
        UIManager.put("TextArea.font", newFont);
        UIManager.put("OptionPane.font", newFont);
    }

    // 根据窗口大小调整组件
    private void adjustComponentsForSize() {
        int width = getWidth();

        // 调整字体大小
        float baseFontSize = 14f;
        float scaleFactor = Math.max(0.8f, Math.min(1.2f, width / 800f));

        questionNumberLabel.setFont(questionNumberLabel.getFont().deriveFont(baseFontSize * 1.4f * scaleFactor));
        questionLabel.setFont(questionLabel.getFont().deriveFont(baseFontSize * 1.7f * scaleFactor));
        resultLabel.setFont(resultLabel.getFont().deriveFont(baseFontSize * 1.4f * scaleFactor));
        timerLabel.setFont(timerLabel.getFont().deriveFont(baseFontSize * 1.3f * scaleFactor));
        selectedNoteLabel.setFont(selectedNoteLabel.getFont().deriveFont(baseFontSize * 1.6f * scaleFactor));
        statsLabel.setFont(statsLabel.getFont().deriveFont(baseFontSize * 1.1f * scaleFactor));

        // 调整按钮大小
        for (JButton btn : noteButtons) {
            float btnScale = Math.max(0.8f, Math.min(1.0f, width / 600f));
            btn.setPreferredSize(new Dimension((int) (60 * btnScale), (int) (40 * btnScale)));
            btn.setFont(btn.getFont().deriveFont(baseFontSize * btnScale));
        }

        // 调整控制按钮大小
        float controlBtnScale = Math.max(0.8f, Math.min(1.0f, width / 600f));
        startButton.setPreferredSize(new Dimension((int) (120 * controlBtnScale), (int) (45 * controlBtnScale)));
        stopButton.setPreferredSize(new Dimension((int) (120 * controlBtnScale), (int) (45 * controlBtnScale)));
        nextButton.setPreferredSize(new Dimension((int) (120 * controlBtnScale), (int) (45 * controlBtnScale)));
    }

    // 创建样式化的音符按钮
    private JButton createStyledNoteButton(String note) {
        JButton button = new JButton(note);
        button.setFont(new Font("微软雅黑", Font.BOLD, 16));
        button.setForeground(Color.WHITE);
        button.setBackground(PRIMARY_COLOR);
        button.setPreferredSize(new Dimension(60, 40));
        button.setBorder(BorderFactory.createEmptyBorder(8, 12, 8, 12));
        button.setFocusPainted(false);

        // 添加悬停效果
        button.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) {
                button.setBackground(BUTTON_HOVER_COLOR);
                button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
            }

            @Override
            public void mouseExited(MouseEvent e) {
                if (!button.getText().equals(selectedNote)) {
                    button.setBackground(PRIMARY_COLOR);
                }
                button.setCursor(Cursor.getDefaultCursor());
            }
        });

        button.addActionListener(e -> {
            if (questionActive) {
                selectNote(note);
                // 直接检查答案
                if (useTimer) {
                    questionTimer.stop();
                }
                checkAnswer();
            }
        });

        button.setFocusable(false); // 防止按钮获取焦点，确保窗体接收键盘事件
        return button;
    }

    // 创建样式化的按钮
    private JButton createStyledButton(String text) {
        JButton button = new JButton(text);
        button.setFont(new Font("微软雅黑", Font.BOLD, 18));
        button.setForeground(Color.WHITE);
        button.setBackground(BUTTON_COLOR);
        button.setPreferredSize(new Dimension(120, 45));
        button.setBorder(BorderFactory.createEmptyBorder(10, 15, 10, 15));
        button.setFocusPainted(false);

        // 添加悬停效果
        button.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) {
                button.setBackground(BUTTON_HOVER_COLOR);
                button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
            }

            @Override
            public void mouseExited(MouseEvent e) {
                button.setBackground(BUTTON_COLOR);
                button.setCursor(Cursor.getDefaultCursor());
            }
        });

        return button;
    }

    // 选择音符
    private void selectNote(String note) {
        if (!questionActive) return;

        selectedNote = note;
        selectedNoteLabel.setText("你选择的是: " + selectedNote);

        // 高亮显示选中的按钮
        for (JButton btn : noteButtons) {
            if (btn.getText().equals(note)) {
                btn.setBackground(WARNING_COLOR);
            } else {
                btn.setBackground(PRIMARY_COLOR);
            }
        }
    }

    // 初始化音符映射
    private void initNotesMap() {
        notesMap = new HashMap<>();
        // E A D G B E (标准调弦的6根弦空弦音)
        // 定义每个品对应的音符 (简化版，只考虑12品以内)
        String[] notes = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};

        // 第6弦 (E)
        for (int i = 0; i <= 12; i++) {
            notesMap.put(600 + i, notes[(4 + i) % 12]); // E是第4个音符
        }

        // 第5弦 (A)
        for (int i = 0; i <= 12; i++) {
            notesMap.put(500 + i, notes[(9 + i) % 12]); // A是第9个音符
        }

        // 第4弦 (D)
        for (int i = 0; i <= 12; i++) {
            notesMap.put(400 + i, notes[(2 + i) % 12]); // D是第2个音符
        }

        // 第3弦 (G)
        for (int i = 0; i <= 12; i++) {
            notesMap.put(300 + i, notes[(7 + i) % 12]); // G是第7个音符
        }

        // 第2弦 (B)
        for (int i = 0; i <= 12; i++) {
            notesMap.put(200 + i, notes[(11 + i) % 12]); // B是第11个音符
        }

        // 第1弦 (E)
        for (int i = 0; i <= 12; i++) {
            notesMap.put(100 + i, notes[(4 + i) % 12]); // E是第4个音符
        }
    }

    // 更新按钮可见性
    private void updateButtonVisibility() {
        String selectedNoteType = (String) noteTypeComboBox.getSelectedItem();

        for (JButton btn : noteButtons) {
            String note = btn.getText();
            boolean visible = false;

            if (selectedNoteType.equals("自然音") && !note.contains("#") && !note.contains("b")) {
                visible = true;
            } else if (selectedNoteType.equals("升号音") && note.contains("#")) {
                visible = true;
            } else if (selectedNoteType.equals("降号音") && note.contains("b")) {
                visible = true;
            }

            btn.setVisible(visible);
        }
    }

    // 开始训练
    private void startTraining() {
        correctCount = 0;
        wrongCount = 0;
        questionCount = 0;
        questionNumberLabel.setText("第 " + questionCount + " 题");
        startButton.setVisible(false);
        stopButton.setEnabled(true);
        stopButton.setVisible(true);

        questionLabel.setText("开始...");
        resultLabel.setText("");
        selectedNote = "";
        selectedNoteLabel.setText("你选择的: ");

        // 重置按钮状态
        for (JButton btn : noteButtons) {
            btn.setBackground(PRIMARY_COLOR);
        }

        // 记录开始时间
        startTime = System.currentTimeMillis();

        // 延迟1秒后生成第一个问题
        Timer timer = new Timer(1000, e -> {
            generateRandomQuestion();
        });
        timer.setRepeats(false);
        timer.start();
    }

    // 停止训练
    private void stopTraining() {
        questionActive = false;
        if (useTimer) {
            questionTimer.stop();
        }

        startButton.setVisible(true);
        stopButton.setEnabled(false);
        nextButton.setEnabled(false);

        questionLabel.setText("训练已停止");
        resultLabel.setText("");
        timerLabel.setText("");
        selectedNote = "";
        selectedNoteLabel.setText("你选择的: ");

        // 重置按钮状态
        for (JButton btn : noteButtons) {
            btn.setBackground(PRIMARY_COLOR);
        }

        // 计算正确率和用时
        int totalCount = correctCount + wrongCount;
        double accuracy = totalCount == 0 ? 0 : (double) correctCount / totalCount * 100;
        long elapsedTime = (System.currentTimeMillis() - startTime) / 1000;

        // 格式化百分比
        DecimalFormat df = new DecimalFormat("#0.00");
        String accuracyStr = df.format(accuracy);

        // 更新统计信息标签
        statsLabel.setText("正确: " + correctCount + " 题, 错误: " + wrongCount + " 题, 正确率: " + accuracyStr + "%, 用时: " + elapsedTime + " 秒");
    }

    // 生成随机问题
    private void generateRandomQuestion() {
        questionCount++;
        questionNumberLabel.setText("第 " + questionCount + " 题");

        Random random = new Random();
        List<Integer> validPositions = new ArrayList<>();

        // 根据选择的音符类型过滤有效的弦和品位置
        String selectedNoteType = (String) noteTypeComboBox.getSelectedItem();

        for (int string = 1; string <= 6; string++) {
            for (int fret = 0; fret <= 12; fret++) {
                String note = notesMap.get(string * 100 + fret);

                if (selectedNoteType.equals("自然音") && !note.contains("#") && !note.contains("b")) {
                    validPositions.add(string * 100 + fret);
                } else if (selectedNoteType.equals("升号音") && note.contains("#")) {
                    validPositions.add(string * 100 + fret);
                } else if (selectedNoteType.equals("降号音") && note.contains("b")) {
                    validPositions.add(string * 100 + fret);
                }
            }
        }

        if (validPositions.isEmpty()) {
            questionLabel.setText("没有符合条件的，请选择其他类型。");
            resultLabel.setText("");
            selectedNote = "";
            selectedNoteLabel.setText("你选择的: ");
            stopButton.setEnabled(true);
            nextButton.setEnabled(true);
            return;
        }

        // 随机选择一个有效的位置
        int position = validPositions.get(random.nextInt(validPositions.size()));
        currentString = position / 100;
        currentFret = position % 100;
        correctAnswer = notesMap.get(position);

        questionLabel.setText(currentString + " 弦， " + currentFret + " 品");
        resultLabel.setText("");
        selectedNote = "";
        selectedNoteLabel.setText("你选择的: ");

        // 重置按钮状态
        for (JButton btn : noteButtons) {
            if (btn.isVisible()) {
                btn.setBackground(PRIMARY_COLOR);
            }
        }

        stopButton.setEnabled(true);
        nextButton.setEnabled(false);

        questionActive = true;
        timeExpired = false;

        if (useTimer) {
            ((QuestionTimerListener) questionTimer.getActionListeners()[0]).secondsLeft = questionTime;
            timerLabel.setText("剩余时间: " + questionTime + "秒");
            questionTimer.restart();
        }

        // 更新按钮可见性
        updateButtonVisibility();
    }

    // 检查答案（时间未到）
    private void checkAnswer() {
        if (selectedNote.isEmpty()) {
            JOptionPane.showMessageDialog(this, "请先选择一个！", "提示", JOptionPane.WARNING_MESSAGE);
            if (useTimer) {
                questionTimer.restart();
            }
            return;
        }

        if (useTimer) {
            questionTimer.stop();
        }
        questionActive = false;

        // 处理降号音符的等价表示
        String userAnswer = selectedNote;
        if (userAnswer.contains("B") && !correctAnswer.contains("B")) {
            userAnswer = convertFlatToSharp(userAnswer);
        }

        if (userAnswer.equals(correctAnswer)) {
            resultLabel.setText("正确！答案是: " + correctAnswer);
            resultLabel.setForeground(SUCCESS_COLOR);
            // 添加成功动画效果
            animateResultLabel(SUCCESS_COLOR);
            correctCount++;

            // 正确的时候不需要点击下一个直接跳到下一题
            Timer timer = new Timer(1000, e -> {
                generateRandomQuestion();
            });
            timer.setRepeats(false);
            timer.start();
        } else {
            resultLabel.setText("错误！正确答案是: " + correctAnswer);
            resultLabel.setForeground(ERROR_COLOR);
            // 添加错误动画效果
            animateResultLabel(ERROR_COLOR);
            wrongCount++;

            // 错误的时候需要手动点击下一题
            stopButton.setEnabled(true);
            nextButton.setEnabled(true);
        }

        // 高亮显示正确答案的按钮
        for (JButton btn : noteButtons) {
            if (btn.getText().equals(correctAnswer)) {
                btn.setBackground(SUCCESS_COLOR);
            } else if (btn.getText().equals(selectedNote)) {
                btn.setBackground(ERROR_COLOR);
            } else {
                btn.setBackground(PRIMARY_COLOR);
            }
        }

        // 更新统计信息标签
        int totalCount = correctCount + wrongCount;
        double accuracy = totalCount == 0 ? 0 : (double) correctCount / totalCount * 100;
        long elapsedTime = (System.currentTimeMillis() - startTime) / 1000;

        // 格式化百分比
        DecimalFormat df = new DecimalFormat("#0.00");
        String accuracyStr = df.format(accuracy);

        statsLabel.setText("正确: " + correctCount + " 题, 错误: " + wrongCount + " 题, 正确率: " + accuracyStr + "%, 用时: " + elapsedTime + " 秒");
    }

    // 检查答案（时间已到）
    private void checkAnswerAfterTimeExpired() {
        if (selectedNote.isEmpty()) {
            return;
        }

        questionActive = false;

        // 处理降号音符的等价表示
        String userAnswer = selectedNote;
        if (userAnswer.contains("B") && !correctAnswer.contains("B")) {
            userAnswer = convertFlatToSharp(userAnswer);
        }

        if (userAnswer.equals(correctAnswer)) {
            resultLabel.setText("正确！答案是: " + correctAnswer);
            resultLabel.setForeground(SUCCESS_COLOR);
            // 添加成功动画效果
            animateResultLabel(SUCCESS_COLOR);
            correctCount++;

            // 正确的时候不需要点击下一个直接跳到下一题
            Timer timer = new Timer(1000, e -> {
                generateRandomQuestion();
            });
            timer.setRepeats(false);
            timer.start();
        } else {
            resultLabel.setText("错误！正确答案是: " + correctAnswer);
            resultLabel.setForeground(ERROR_COLOR);
            // 添加错误动画效果
            animateResultLabel(ERROR_COLOR);
            wrongCount++;

            // 错误的时候需要手动点击下一题
            stopButton.setEnabled(true);
            nextButton.setEnabled(true);
        }

        // 高亮显示正确答案的按钮
        for (JButton btn : noteButtons) {
            if (btn.getText().equals(correctAnswer)) {
                btn.setBackground(SUCCESS_COLOR);
            } else if (btn.getText().equals(selectedNote)) {
                btn.setBackground(ERROR_COLOR);
            } else {
                btn.setBackground(PRIMARY_COLOR);
            }
        }

        // 更新统计信息标签
        int totalCount = correctCount + wrongCount;
        double accuracy = totalCount == 0 ? 0 : (double) correctCount / totalCount * 100;
        long elapsedTime = (System.currentTimeMillis() - startTime) / 1000;

        // 格式化百分比
        DecimalFormat df = new DecimalFormat("#0.00");
        String accuracyStr = df.format(accuracy);

        statsLabel.setText("正确: " + correctCount + " 题, 错误: " + wrongCount + " 题, 正确率: " + accuracyStr + "%, 用时: " + elapsedTime + " 秒");
    }

    // 结果标签动画效果
    private void animateResultLabel(Color color) {
        class AnimationTimer {
            private int count = 0;
            private Timer timer;

            public AnimationTimer() {
                timer = new Timer(50, e -> {
                    if (count < 5) {
                        resultLabel.setForeground(count % 2 == 0 ? color : Color.BLACK);
                        count++;
                    } else {
                        resultLabel.setForeground(color);
                        timer.stop();
                    }
                });
                timer.start();
            }
        }

        new AnimationTimer();
    }

    // 将降号音符转换为等价的升号音符
    private String convertFlatToSharp(String flatNote) {
        Map<String, String> flatToSharpMap = new HashMap<>();
        flatToSharpMap.put("Db", "C#");
        flatToSharpMap.put("Eb", "D#");
        flatToSharpMap.put("Gb", "F#");
        flatToSharpMap.put("Ab", "G#");
        flatToSharpMap.put("Bb", "A#");

        return flatToSharpMap.getOrDefault(flatNote, flatNote);
    }

    // 开始按钮监听器
    private class StartButtonListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            startTraining();
        }
    }

    // 停止按钮监听器
    private class StopButtonListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            stopTraining();
        }
    }

    // 下一个按钮监听器
    private class NextButtonListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            generateRandomQuestion();
        }
    }

    // 问题计时器监听器
    private class QuestionTimerListener implements ActionListener {
        private int secondsLeft = questionTime;

        @Override
        public void actionPerformed(ActionEvent e) {
            if (!useTimer) {
                questionTimer.stop();
                return;
            }

            secondsLeft--;
            timerLabel.setText("剩余时间: " + secondsLeft + "秒");

            timerLabel.setForeground(PRIMARY_COLOR);

            if (secondsLeft <= 0) {
                questionTimer.stop();
                timeExpired = true;
                timerLabel.setText("时间到！");
                timerLabel.setForeground(ERROR_COLOR);

                if (!selectedNote.isEmpty()) {
                    checkAnswerAfterTimeExpired();
                } else {
                    stopButton.setEnabled(true);
                    nextButton.setEnabled(true);
                }
            }
        }
    }

    // 自定义WrapLayout类，支持自动换行
    private static class WrapLayout extends FlowLayout {
        public WrapLayout(int align, int hgap, int vgap) {
            super(align, hgap, vgap);
        }

        @Override
        public Dimension preferredLayoutSize(Container target) {
            return layoutSize(target, true);
        }

        @Override
        public Dimension minimumLayoutSize(Container target) {
            Dimension minimum = layoutSize(target, false);
            minimum.width -= (getHgap() + 1);
            return minimum;
        }

        private Dimension layoutSize(Container target, boolean preferred) {
            synchronized (target.getTreeLock()) {
                int targetWidth = target.getSize().width;
                if (targetWidth == 0) {
                    targetWidth = Integer.MAX_VALUE;
                }

                int hgap = getHgap();
                int vgap = getVgap();
                Insets insets = target.getInsets();
                int horizontalInsetsAndGap = insets.left + insets.right + (hgap * 2);
                int maxWidth = targetWidth - horizontalInsetsAndGap;

                Dimension dim = new Dimension(0, 0);
                int rowWidth = 0;
                int rowHeight = 0;

                int nmembers = target.getComponentCount();

                for (int i = 0; i < nmembers; i++) {
                    Component m = target.getComponent(i);
                    if (m.isVisible()) {
                        Dimension d = preferred ? m.getPreferredSize() : m.getMinimumSize();

                        if (rowWidth + d.width > maxWidth) {
                            addRow(dim, rowWidth, rowHeight);
                            rowWidth = 0;
                            rowHeight = 0;
                        }

                        if (rowWidth != 0) {
                            rowWidth += hgap;
                        }
                        rowWidth += d.width;
                        rowHeight = Math.max(rowHeight, d.height);
                    }
                }

                addRow(dim, rowWidth, rowHeight);

                dim.width += horizontalInsetsAndGap;
                dim.height += insets.top + insets.bottom + vgap * 2;

                return dim;
            }
        }

        private void addRow(Dimension dim, int rowWidth, int rowHeight) {
            dim.width = Math.max(dim.width, rowWidth);
            if (dim.height > 0) {
                dim.height += getVgap();
            }
            dim.height += rowHeight;
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(GuitarFretboardTrainer::new);
    }
}